#include "XmlFile.h"

XMLFile::XMLFile(  string & szFileName ,  string & rootName)
{
	if(!isXmlFileExist(szFileName))
	{
		if(!CreateXmlFile(szFileName , rootName))
		{
			m_XMLDoc = NULL;
			return;
		}
	}
	
	m_XMLDoc  = xmlReadFile(szFileName.c_str(),"utf-8",XML_PARSE_RECOVER);
	m_szFileName = szFileName;

}

XMLFile::XMLFile()
{
	m_XMLDoc = NULL;
}

bool XMLFile::isXmlFileExist( string &  szFileName )
{
	FILE *fp = fopen(szFileName.c_str(), "r");
	bool bRet = false;

	if (fp)
	{
		bRet = true;
		fclose(fp);
	}

	return bRet;
}

bool XMLFile::CreateXmlFile( string & szFilename , string & rootName )
{
	 bool bRet = false;
	 xmlDocPtr doc = NULL;
	 

	 do 
	 {
		 doc = xmlNewDoc(BAD_CAST"1.0");
		 if(doc == NULL)
		 {
			 break;
		 }

		 xmlNodePtr rootNode = xmlNewNode(NULL, BAD_CAST rootName.c_str());
		 if (rootNode == NULL)
		 {
			 //CCLOG("can not create root node");
			 break;
		 }

		 // set root node
		 xmlDocSetRootElement(doc, rootNode);

		 // save xml file
		 xmlSaveFile(szFilename.c_str(), doc);

		 bRet = true;

	 } while ( 0 );
		
	 if(doc)
	 {
			xmlFreeDoc(doc);
	 }

	 return bRet;
}

XMLFile::~XMLFile()
{
	flush();
	if(m_XMLDoc)
	{
		xmlFreeDoc(m_XMLDoc);
		m_XMLDoc = NULL;
	}
}



void XMLFile::setvalueForKey( const char * pKey , const char * pValue )
{

	xmlNodePtr rootNode;
	xmlNodePtr node;

	// check the params
	if (! pKey || ! pValue)
	{
		return;
	}

	// find the node
	node = getXMLNodeForKey(pKey, &rootNode);

	// if node exist, change the content
	if (node)
	{
		xmlNodeSetContent(node, BAD_CAST pValue);
	}
	else
	{
		if (rootNode)
		{
			// the node doesn't exist, add a new one
			// libxml in android donesn't support xmlNewTextChild, so use this approach
			xmlNodePtr tmpNode = xmlNewNode(NULL, BAD_CAST pKey);
			xmlNodePtr content = xmlNewText(BAD_CAST pValue);
			xmlAddChild(rootNode, tmpNode);
			xmlAddChild(tmpNode, content);
		}    
	}
}

xmlNodePtr XMLFile::getXMLNodeForKey( const char * pKey , xmlNodePtr * rootNode )
{
	xmlNodePtr curNode = NULL;

	// check the key value
	if (! pKey)
	{
		return NULL;
	}

	do 
	{
		// get root node
		*rootNode = xmlDocGetRootElement(m_XMLDoc);
		if (NULL == *rootNode)
		{
			//CCLOG("read root node error");
			break;
		}

		// find the node
		curNode = (*rootNode)->xmlChildrenNode;
		while (NULL != curNode)
		{
			if (! xmlStrcmp(curNode->name, BAD_CAST pKey))
			{
				break;
			}

			curNode = curNode->next;
		}
	} while (0);

	return curNode;
}

void XMLFile::setStringForKey( const char * pKey , const string & pString )
{
	if(! pKey)
		return;

	setvalueForKey(pKey, pString.c_str());
}

void XMLFile::setIntForKey( const char * pKey , int aValue )
{
	if( !pKey)
		return;

	char tmp[50];
	memset(tmp,0,50);
	sprintf(tmp, "%d" , aValue);
	setvalueForKey(pKey,tmp);
}

void XMLFile::setFloatForKey( const char * pKey , float aValue )
{
	if(!pKey)
	{
		return;
	}
	char tmp[50];
	memset(tmp,0,50);
	sprintf(tmp, "%f" , aValue);
	setvalueForKey(pKey,tmp);
}

void XMLFile::setBoolForKey( const char * pKey , bool aValue )
{
	if (true == aValue)
	{
		setStringForKey(pKey, "true");
	}
	else
	{
		setStringForKey(pKey, "false");
	}
}

std::string XMLFile::getStringForKey( const char * pKey , string & defaultValue )
{

	const char* value = getValueForKey(pKey);
	string ret = defaultValue;

	if (value)
	{
		ret = string(value);
		xmlFree((void*)value);
	}

	return ret;
}

const char * XMLFile::getValueForKey( const char * pKey )
{
	const char* ret = NULL;
	xmlNodePtr rootNode;
	xmlNodePtr node = getXMLNodeForKey(pKey, &rootNode);

	// find the node
	if (node)
	{
		ret = (const char*)xmlNodeGetContent(node);
	}

	return ret;
}

int XMLFile::getIntForKey( const char * pKey , int defaultValue )
{
	const char* value = getValueForKey(pKey);
	int ret = defaultValue;

	if (value)
	{
		ret = atoi(value);
		xmlFree((void*)value);
	}

	return ret;
}

float XMLFile::getFloatForKey( const char * pKey , float defaultValue )
{
	const char* value = getValueForKey(pKey);
	double ret = defaultValue;

	if (value)
	{
		ret = atof(value);
		xmlFree((void*)value);
	}

	return ret;
}

bool XMLFile::getBoolForKey( const char * pKey , bool defaultValue )
{
	const char* value = getValueForKey(pKey);
	bool ret = defaultValue;

	if (value)
	{
		ret = (! strcmp(value, "true"));
		xmlFree((void*)value);
	}

	return ret;
}

void XMLFile::flush()
{
	if(m_XMLDoc)
	{
		 xmlSaveFile(m_szFileName.c_str(), m_XMLDoc);
	}
}

void XMLFile::Init( string & szFileName , string & rootName )
{
	if(m_XMLDoc) return;
	if(!isXmlFileExist(szFileName))
	{
		if(!CreateXmlFile(szFileName , rootName))
		{
			m_XMLDoc = NULL;
			return;
		}
	}

	m_XMLDoc  = xmlReadFile(szFileName.c_str(),"utf-8",XML_PARSE_RECOVER);
	m_szFileName = szFileName;
}
